package us.yesor.atlast;

import java.util.HashMap;




import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;

public class AtLastContentProvider extends ContentProvider {

	private static final String DATABASE_NAME = "AtLastDB";
	private static final int DATABASE_VERSION = 1;
	public static final String AUTHORITY = "us.yesor.atlast.AtLastContentProvider";
	private DatabaseHelper dbHelper;
	// Pass a query to the interactions table
	private static final int INTERACTIONS = 1;
	// No query if already know the interaction id
	private static final int INTERACTION_ID = 2;
	// Special formatted query for collection info
	private static final int COLLECTIONS = 3;
	// Special formatted query for item history
	private static final int HISTORY = 4;
	private static final UriMatcher sUriMatcher;
	private static HashMap<String, String> projectionMap;

	private static class DatabaseHelper extends SQLiteOpenHelper {

		private static final String TAG = "AtLastDatabaseHelper";

		private static final String CREATE_INTERACTIONS_TABLE = "create table "
				+ InteractionTable.TABLE_NAME + " (" + InteractionTable.IID
				+ " integer primary key autoincrement, "
				+ InteractionTable.COLLECTION + " text, "
				+ InteractionTable.ITEM + " text, " + InteractionTable.TRIGGER
				+ " text, " + InteractionTable.VALUE + " text, "
				+ InteractionTable.STATE + " text, " + InteractionTable.TIME
				+ " text);";

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("DROP TABLE IF EXISTS " + InteractionTable.TABLE_NAME);
			db.execSQL(CREATE_INTERACTIONS_TABLE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS " + InteractionTable.TABLE_NAME);
			onCreate(db);
		}
	}

	@Override
	public boolean onCreate() {
		dbHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		int count = 0;
		switch (sUriMatcher.match(uri)) {
		case INTERACTIONS:
			count = db.delete(InteractionTable.TABLE_NAME, selection,
					selectionArgs);
			break;
		case INTERACTION_ID:
			String iid = uri.getPathSegments().get(
					InteractionTable.IID_PATH_POSITION);
			String finalWhere = InteractionTable.IID + "=" + iid;
			if (selection != null) {
				finalWhere = finalWhere + " AND " + selection;
			}
			count = db.delete(InteractionTable.TABLE_NAME, finalWhere,
					selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown Uri: " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case INTERACTIONS:
			return InteractionTable.CONTENT_TYPE;
		case INTERACTION_ID:
			return InteractionTable.CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown Uri " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		if (sUriMatcher.match(uri) != INTERACTIONS) {
			throw new IllegalArgumentException("Unknown Uri "+uri);
		}
		ContentValues cv;
		if (values != null) {
			cv = new ContentValues(values);
		} else {
			cv = new ContentValues();
		}
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		long rowId = db.insert(InteractionTable.TABLE_NAME, InteractionTable.ITEM, cv);
		if (rowId > 0) {
			Uri interactionUri = ContentUris.withAppendedId(InteractionTable.CONTENT_URI, rowId);
			getContext().getContentResolver().notifyChange(interactionUri, null);
			return interactionUri;
		}
		throw new SQLException("Failed to insert row into "+ uri);
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(InteractionTable.TABLE_NAME);
		Cursor c;
		switch (sUriMatcher.match(uri)) {
		case HISTORY:
			qb.setProjectionMap(projectionMap);
			c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
			c.setNotificationUri(getContext().getContentResolver(), uri);
			return c;
		case INTERACTIONS:
//			String newSelection = "SELECT "+InteractionTable.IID+", "+InteractionTable.ITEM+", "
//			+InteractionTable.STATE +", MAX("+InteractionTable.TIME+") FROM "
//			+InteractionTable.TABLE_NAME+" WHERE "+InteractionTable.COLLECTION+" = ?  GROUP BY "
//			+InteractionTable.ITEM;
			String newSelection="SELECT _id, item, state, time FROM interaction WHERE collection ="
					+" ? GROUP BY item";
			c = db.rawQuery(newSelection, selectionArgs);
//			How to use the query builder for this?  Need to include MAX(time), etc.
//			qb.setProjectionMap(projectionMap);
//			c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
			c.setNotificationUri(getContext().getContentResolver(), uri);
			return c;
		case INTERACTION_ID:
			String iid = uri.getPathSegments().get(
					InteractionTable.IID_PATH_POSITION);
			qb.setProjectionMap(projectionMap);
			qb.appendWhere(InteractionTable.IID + "=" + iid);
			c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
			c.setNotificationUri(getContext().getContentResolver(), uri);
			return c;
		case COLLECTIONS:
			//TODO must be a better way -- is this a kludge?
			String collectionSelection = "SELECT "+InteractionTable.IID+", "+InteractionTable.COLLECTION+", COUNT(DISTINCT " +
					InteractionTable.ITEM+"), MAX("+InteractionTable.TIME+") FROM "+InteractionTable.TABLE_NAME+
					" WHERE "+InteractionTable.COLLECTION+" IN (SELECT DISTINCT "+InteractionTable.COLLECTION+
					" FROM "+InteractionTable.TABLE_NAME+" ) GROUP BY "+InteractionTable.COLLECTION;
			c = db.rawQuery(collectionSelection, selectionArgs);
			c.setNotificationUri(getContext().getContentResolver(), uri);
			return c;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		int count = 0;
		switch (sUriMatcher.match(uri)) {
		case INTERACTIONS:
			count = db.update(InteractionTable.TABLE_NAME, values, selection,
					selectionArgs);
			break;
		case INTERACTION_ID:
			String iid = uri.getPathSegments().get(
					InteractionTable.IID_PATH_POSITION);
			String finalWhere = InteractionTable.IID + " = " + iid;
			if (selection != null) {
				finalWhere = finalWhere + " AND " + selection;
			}
			count = db.update(InteractionTable.TABLE_NAME, values, finalWhere,
					selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(AUTHORITY, "interaction", INTERACTIONS);
		sUriMatcher.addURI(AUTHORITY, "interaction/#", INTERACTION_ID);
		sUriMatcher.addURI(AUTHORITY, "interaction/collections", COLLECTIONS);
		sUriMatcher.addURI(AUTHORITY, "interaction/history", HISTORY);
		projectionMap = new HashMap<String, String>();
		projectionMap.put(InteractionTable.IID, InteractionTable.IID);
		projectionMap.put(InteractionTable.COLLECTION,
				InteractionTable.COLLECTION);
		projectionMap.put(InteractionTable.ITEM, InteractionTable.ITEM);
		projectionMap.put(InteractionTable.TRIGGER, InteractionTable.TRIGGER);
		projectionMap.put(InteractionTable.VALUE, InteractionTable.VALUE);
		projectionMap.put(InteractionTable.STATE, InteractionTable.STATE);
		projectionMap.put(InteractionTable.TIME, InteractionTable.TIME);

	}

}
